<?php

// monitor.php

// --- 配置 ---
require_once 'db_config.php'; // 引入数据库配置
define('MONITOR_INTERVAL_SECONDS', 10); // 监控刷新间隔（秒）
define('ALARM_SOUND_FILE', '14016.wav'); // 报警声音文件路径

// --- 辅助函数 ---

/**
 * 记录监控事件到 MySQL 数据库。
 * 此函数现在记录所有事件（成功和失败）。
 * @param string $url URL
 * @param int|string $statusCode HTTP 状态码
 * @param string $statusMessage 状态信息
 * @param float $responseTime 响应时间
 * @param array $extraDetails 更多详细信息（可选，例如 CURL 错误信息）
 */
function logToMysql($url, $statusCode, $statusMessage, $responseTime, $extraDetails = []) {
    $conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
    if ($conn->connect_error) {
        // 将连接错误记录到 PHP 错误日志，但不要中断脚本执行
        error_log("MySQL 连接失败: " . $conn->connect_error);
        return;
    }

    // 确保所有详细信息可以序列化为 JSON
    $jsonDetails = json_encode($extraDetails, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    if ($jsonDetails === false) {
        error_log("JSON 编码错误: " . json_last_error_msg());
        $jsonDetails = "{}"; // 如果编码失败，默认为空 JSON
    }

    // 准备插入到 monitor_logs 表的语句
    $stmt = $conn->prepare("INSERT INTO monitor_logs (url, status_code, status_message, response_time, log_time, details) VALUES (?, ?, ?, ?, NOW(), ?)");

    // 修复：正确的 bind_param 类型和数量
    // s: URL (字符串)
    // s: status_code (可以是 N/A, 所以是字符串)
    // s: status_message (字符串)
    // d: response_time (十进制数, 对应 bind_param 的 double 类型)
    // s: details (JSON 字符串)
    $stmt->bind_param("sssds", $url, $statusCode, $statusMessage, $responseTime, $jsonDetails);

    if (!$stmt->execute()) {
        error_log("MySQL 插入错误 (URL: " . $url . "): " . $stmt->error);
    }

    $stmt->close();
    $conn->close();
}


/**
 * 监控给定 URL 的状态。
 * @param string $url 要监控的 URL
 * @return array (is_success, status_code, status_message, response_time, curl_info)
 */
function monitorUrl($url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 5); // 设置 5 秒超时
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_NOBODY, true); // 只获取头部信息，不下载内容以加快速度
    curl_setopt($ch, CURLOPT_HEADER, true); // 获取响应头以获取更多详细信息

    $start_time = microtime(true);
    curl_exec($ch); // 执行 CURL 请求
    $end_time = microtime(true);

    $responseTime = $end_time - $start_time;
    $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curlError = curl_error($ch);
    $curlErrno = curl_errno($ch);

    // 提取完整的 CURL 信息用于日志记录
    $curlInfo = curl_getinfo($ch);
    curl_close($ch);

    $extraDetails = [
        'curl_error' => $curlError,
        'curl_errno' => $curlErrno,
        'http_version' => isset($curlInfo['http_version']) ? $curlInfo['http_version'] : '',
        'redirect_count' => isset($curlInfo['redirect_count']) ? $curlInfo['redirect_count'] : 0,
        'primary_ip' => isset($curlInfo['primary_ip']) ? $curlInfo['primary_ip'] : '',
        'total_time' => isset($curlInfo['total_time']) ? $curlInfo['total_time'] : 0,
        'namelookup_time' => isset($curlInfo['namelookup_time']) ? $curlInfo['namelookup_time'] : 0,
        'connect_time' => isset($curlInfo['connect_time']) ? $curlInfo['connect_time'] : 0,
        'pretransfer_time' => isset($curlInfo['pretransfer_time']) ? $curlInfo['pretransfer_time'] : 0,
        'starttransfer_time' => isset($curlInfo['starttransfer_time']) ? $curlInfo['starttransfer_time'] : 0,
        'appconnect_time' => isset($curlInfo['appconnect_time']) ? $curlInfo['appconnect_time'] : 0, // SSL 握手时间
        'size_download' => isset($curlInfo['size_download']) ? $curlInfo['size_download'] : 0, // 下载大小
        'speed_download' => isset($curlInfo['speed_download']) ? $curlInfo['speed_download'] : 0, // 下载速度
    ];

    if ($curlError) {
        return [false, 'N/A', "CURL 错误: " . $curlError, 0, $extraDetails];
    } elseif ($statusCode >= 200 && $statusCode < 300) {
        return [true, $statusCode, "可访问", $responseTime, $extraDetails];
    } else {
        return [false, $statusCode, "HTTP 错误", $responseTime, $extraDetails];
    }
}

// --- 主程序逻辑 ---

$urlsToMonitor = [];
if (isset($_POST['urls'])) {
    $decodedUrls = urldecode($_POST['urls']);
    $urlsToMonitor = array_filter(array_map('trim', explode("\n", $decodedUrls)));
} elseif (isset($_GET['urls'])) {
    $decodedUrls = urldecode($_GET['urls']);
    $urlsToMonitor = array_filter(array_map('trim', explode(',', $decodedUrls)));
}

$urlsToMonitor = array_unique($urlsToMonitor);

// Check if alarm was explicitly muted by user (via GET or POST from refresh)
$muteAlarm = (isset($_GET['mute_alarm']) && $_GET['mute_alarm'] === 'true') ||
    (isset($_POST['mute_alarm']) && $_POST['mute_alarm'] === 'true');
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>域名监控面板</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; background-color: #f4f4f4; color: #333; }
        .container { max-width: 900px; margin: auto; background: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
        h1, h2 { color: #0056b3; }
        .input-form label { display: block; margin-bottom: 5px; font-weight: bold; }
        .input-form textarea { width: calc(100% - 22px); height: 100px; padding: 10px; margin-bottom: 10px; border: 1px solid #ddd; border-radius: 4px; resize: vertical; }
        .input-form input[type="submit"] { padding: 10px 20px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; }
        .input-form input[type="submit"]:hover { background-color: #0056b3; }
        .countdown { margin-top: 20px; text-align: center; font-size: 1.2em; color: #555; }
        .alarm-controls { text-align: center; margin-top: 10px; }
        .alarm-controls button { background-color: #dc3545; color: white; border: none; padding: 8px 15px; border-radius: 4px; cursor: pointer; }
        .alarm-controls button:hover { background-color: #c82333; }
        .status-table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        .status-table th, .status-table td { border: 1px solid #ddd; padding: 10px; text-align: left; }
        .status-table th { background-color: #f2f2f2; }
        .status-table tr:nth-child(even) { background-color: #f9f9f9; }
        .success { color: green; font-weight: bold; }
        .failure { color: red; font-weight: bold; }
        .log-link { margin-top: 20px; text-align: center; }
        .log-link a { color: #007bff; text-decoration: none; }
        .log-link a:hover { text-decoration: underline; }
        .reset-button {
            background-color: #6c757d; /* Bootstrap secondary color */
            color: white;
            border: none;
            padding: 8px 15px;
            border-radius: 4px;
            cursor: pointer;
            margin-left: 10px; /* Add some spacing */
        }
        .reset-button:hover {
            background-color: #5a6268;
        }

        .read-button {
            background-color: #616263; /* Bootstrap secondary color */
            color: white;
            border: none;
            padding: 8px 15px 8px;
            border-radius: 4px;
            cursor: pointer;
            margin-right:10px;
        }
        .read-button:hover {
            background-color: #5a6268;
        }
    </style>
</head>
<body>
<div class="container">
    <h1>域名监控面板</h1>
    <audio id="alarmSound" src="<?php echo htmlspecialchars(ALARM_SOUND_FILE); ?>" preload="auto" loop></audio>

    <?php if (empty($urlsToMonitor)): ?>
        <div class="input-form">
            <h2>请输入要监控的链接 (每行一个)</h2>
            <form action="" method="post">
                <label for="urls">链接:</label>
                <textarea id="urls" name="urls" placeholder="https://www.google.com&#10;https://www.example.org&#10;http://localhost"></textarea>
                <input type="submit" value="开始监控">
            </form>

            <div style="margin-top:20px;">
                <button class="read-button" onclick="window.open('view_log.php', '_blank')">查看完整监控日志</button>
                <button class="read-button" onclick="window.open('view_visit_log.php', '_blank')">查看网站访问日志</button>
            </div>

        </div>
    <?php else: ?>
        <div class="countdown">
            下次刷新倒计时: <span id="countdownDisplay"><?php echo MONITOR_INTERVAL_SECONDS; ?></span> 秒
        </div>
        <p>最近一次监控时间: **<?php echo date("Y-m-d H:i:s"); ?>**</p>
        <table class="status-table">
            <thead>
            <tr>
                <th>URL</th>
                <th>状态</th>
                <th>响应时间 (秒)</th>
            </tr>
            </thead>
            <tbody>
            <?php
            $currentUrlsDisplay = implode("\n", $urlsToMonitor);
            $hasError = false; // 标志位，检查是否有任何 URL 失败

            foreach ($urlsToMonitor as $url) {
                list($isSuccess, $statusCode, $statusMessage, $responseTime, $extraDetails) = monitorUrl($url);
                logToMysql($url, $statusCode, $statusMessage, $responseTime, $extraDetails); // 将所有事件记录到 MySQL

                if (!$isSuccess) {
                    $hasError = true; // 如果发生错误，设置标志
                }
                ?>
                <tr>
                    <td><?php echo htmlspecialchars($url); ?></td>
                    <td>
                        <?php if ($isSuccess): ?>
                            <span class="success">🟢 可访问 (HTTP <?php echo htmlspecialchars($statusCode); ?>)</span>
                        <?php else: ?>
                            <span class="failure">🔴 <?php echo htmlspecialchars($statusMessage); ?> (HTTP <?php htmlspecialchars($statusCode); ?>)</span>
                        <?php endif; ?>
                    </td>
                    <td>
                        <?php if ($isSuccess): ?>
                            <?php echo sprintf("%.4f", $responseTime); ?>
                        <?php else: ?>
                            N/A
                        <?php endif; ?>
                    </td>
                </tr>
                <?php
            }
            ?>
            </tbody>
        </table>

        <div class="alarm-controls">
            <?php if ($hasError): ?>
                <button id="muteAlarmBtn">🔇 静音报警</button>
            <?php endif; ?>
        </div>

        <div class="log-link">
            <p>查看 <a href="view_log.php" target="_blank">完整监控日志 (MySQL)</a></p>
            <button class="reset-button" onclick="location.href='index.php'">回到初始化</button>
        </div>

        <script>
            const countdownDisplay = document.getElementById('countdownDisplay');
            const alarmSound = document.getElementById('alarmSound');
            const muteAlarmBtn = document.getElementById('muteAlarmBtn');
            let timeLeft = <?php echo MONITOR_INTERVAL_SECONDS; ?>;
            const hasError = <?php echo json_encode($hasError); ?>;
            // 从 sessionStorage 读取报警静音状态，如果存在则使用，否则使用 PHP 传递的值
            let alarmMuted = sessionStorage.getItem('alarmMuted') === 'true' || <?php echo json_encode($muteAlarm); ?>;

            // 如果有错误并且未静音，尝试播放报警声音
            if (hasError && !alarmMuted) {
                const playPromise = alarmSound.play();
                if (playPromise !== undefined) {
                    playPromise.then(_ => {
                        // 自动播放成功！
                    }).catch(error => {
                        console.warn("报警声音自动播放被阻止，可能没有用户手势:", error);
                        // 如果自动播放被阻止，提示用户点击
                        if (!sessionStorage.getItem('autoplayPrompted')) {
                            // alert("注意: 某个监控的域名已宕机！请点击页面任意位置以听到警报声。"); // 可以考虑更友好的提示方式
                            sessionStorage.setItem('autoplayPrompted', 'true');
                        }
                        document.body.addEventListener('click', () => {
                            alarmSound.play().catch(e => console.error("手动播放失败:", e));
                        }, {once: true}); // 第一次点击时尝试播放
                    });
                }
            }

            // 处理静音按钮点击事件
            if (muteAlarmBtn) {
                muteAlarmBtn.addEventListener('click', () => {
                    alarmSound.pause();
                    alarmSound.currentTime = 0; // 将声音重置到开头
                    alarmMuted = true;
                    sessionStorage.setItem('alarmMuted', 'true'); // 将静音状态持久化
                    muteAlarmBtn.style.display = 'none'; // 静音后隐藏按钮
                });
            }

            // 如果没有错误，确保报警声音停止播放并清除静音状态
            if (!hasError && alarmSound) {
                alarmSound.pause();
                alarmSound.currentTime = 0;
                sessionStorage.removeItem('alarmMuted');
                sessionStorage.removeItem('autoplayPrompted'); // 清除提示，以便下次出现错误时再次提示
            }


            function updateCountdown() {
                countdownDisplay.textContent = timeLeft;
                timeLeft--;

                if (timeLeft < 0) {
                    const form = document.createElement('form');
                    form.method = 'POST';
                    form.action = window.location.pathname;

                    const input = document.createElement('input');
                    input.type = 'hidden';
                    input.name = 'urls';
                    input.value = encodeURIComponent(`<?php echo addslashes($currentUrlsDisplay); ?>`);

                    // 通过 POST 将静音状态传递给下一次页面加载
                    if (alarmMuted) {
                        const muteInput = document.createElement('input');
                        muteInput.type = 'hidden';
                        muteInput.name = 'mute_alarm';
                        muteInput.value = 'true';
                        form.appendChild(muteInput);
                    }

                    form.appendChild(input);
                    document.body.appendChild(form);
                    form.submit();

                } else {
                    setTimeout(updateCountdown, 1000);
                }
            }

            window.onload = updateCountdown;
        </script>
    <?php endif; ?>
</div>
</body>
</html>
